//接收函数
import { arrayBufferToHexString } from 'src/hook/common/useUitil';

//接收函数
type WsRevFunc = (e: any) => void;

//事件函数
type WsEvtFunc = () => void;

//Websocket状态
export enum EnumWebsocketState {
  WS_NULL = -1,
  WS_CONNECTING,
  WS_OPEN,
  WS_CLOSING,
  WS_CLOSED
}

//连接socket封装
export interface CSocket {
  websocket: any,
  connectURL: string,
  socket_open: boolean,
  heartbeat_timer: any,
  heartbeat_interval: number,
  is_reconnect: boolean,
  reconnect_count: number,
  reconnect_current: number,
  fail_number: number,
  reconnect_timer: any,
  reconnect_interval: number,
  heart_buffer: number[],

  init: (onReceived: WsRevFunc, onConnected?: WsEvtFunc, onClosed?: WsEvtFunc, onTransmitted?: WsEvtFunc,
         heartBuffer?: number[]) => any,
  connect: (url?: string) => void,
  heartbeat: () => void,
  send: (data: any) => void,
  close: () => void,
  reconnect: () => void,
  getStatus: () => number,
  pfnOnReceived?: ((message: any) => void) | null,
  pfnOnConnected?: (() => void) | null,
  pfnOnClosed?: (() => void) | null,
  pfnOnTransmitted?: (() => void) | null
}

export const socket: CSocket = {
  //websocket对象
  websocket: null,

  //连接地址
  connectURL: '',

  // 开启标识
  socket_open: false,

  // 心跳timer
  heartbeat_timer: null,

  // 心跳发送频率
  heartbeat_interval: 45000,

  // 是否自动重连
  is_reconnect: false,

  // 重连次数
  reconnect_count: 3,

  // 已发起重连次数
  reconnect_current: 1,

  // 网络错误提示此时
  fail_number: 0,

  // 重连timer
  reconnect_timer: null,

  // 重连频率
  reconnect_interval: 10000,

  heart_buffer: [],
  pfnOnConnected: null,
  pfnOnClosed: null,
  pfnOnTransmitted: null,
  pfnOnReceived: null,

  //初始化相关参数
  init: (onReceived: WsRevFunc, onConnected?: WsEvtFunc, onClosed?: WsEvtFunc,
    onTransmitted?: WsEvtFunc, heartBuffer?: number[])  => {
    if (onConnected) {
      socket.pfnOnConnected = onConnected;
    }
    if (onClosed) {
      socket.pfnOnClosed = onClosed;
    }
    if (onTransmitted) {
      socket.pfnOnTransmitted = onTransmitted;
    }

    if (onReceived) {
      socket.pfnOnReceived = onReceived;
    }

    if ((heartBuffer) && (heartBuffer?.length > 0)) {
      heartBuffer.forEach((el) => {
        socket.heart_buffer.push(el);
      });
    }
  },

  //receiveMessage的返回值是函数 返回函数的返回值是void
  connect: (url?: string)  => {
    if (!('WebSocket' in window)) {
      console.log('当前浏览器不支持websocket！');
      return null;
    }

    // 已经创建过连接不再重复创建
    if (socket.websocket) {
      console.log('Websocket exists!');
      return socket.websocket;
    }

    //创建websocket
    if (url) {
      socket.connectURL = url;
    }
    socket.websocket = new WebSocket(socket.connectURL);

    //发送采用字节流，默认时采用字符串
    socket.websocket.binaryType = 'arraybuffer';

    // 连接成功
    socket.websocket.onopen = function () {
      socket.socket_open = true;
      socket.is_reconnect = true;
      socket.fail_number = 0;

      //通知事件
      if (socket.pfnOnConnected) {
        socket.pfnOnConnected();
      }

      //开启心跳
      //socket.heartbeat();
    }

    //接收到消息， e为ArrayBuffer
    socket.websocket.onmessage = (e: any) => {
      if (socket.pfnOnReceived) {
        let binaryData = e.data;

        //转换为16进制
        let uint8Arr = new Uint8Array(binaryData);
        for (let i = 0; i < binaryData.length; i++) {
          uint8Arr[i] = binaryData[i];
        }

        //转换为字符串
        console.log(arrayBufferToHexString(uint8Arr));
        socket.pfnOnReceived(uint8Arr.buffer);
      }
    }

    //关闭连接
    socket.websocket.onclose = (e: any) => {
      clearInterval(socket.heartbeat_interval)
      socket.websocket = null;
      socket.socket_open = false;
      socket.fail_number = 0;
      console.log('Websocket is closed!');

      //需要重新连接
      if (socket.is_reconnect) {
        //重连定时器
        socket.reconnect_timer = setTimeout(() => {
          // 超过重连次数, 报错退出
          if (socket.reconnect_current > socket.reconnect_count) {
            clearTimeout(socket.reconnect_timer);
            socket.is_reconnect = false;
            if (socket.pfnOnClosed) {
              socket.pfnOnClosed();
            }
          } else {
            //记录重连次数
            socket.reconnect_current++;
            socket.reconnect();
          }
        }, socket.reconnect_interval);
      } else {
        if (socket.pfnOnClosed) {
          socket.pfnOnClosed();
        }
      }
    }


    // 连接发生错误
    socket.websocket.onerror = () => {
      console.log('Websocket connection is error!');
      socket.close();
      socket.websocket = null;
      socket.fail_number = 0;
      if (socket.pfnOnClosed) {
        socket.pfnOnClosed();
      }
    }
  },

  send: (data: []) => {
    if ((socket.websocket) && (socket.websocket.readyState === socket.websocket.OPEN)) {
      //data为普通数组,需要转换为ArrayBuffer字节流发送
      let buffer = new ArrayBuffer(data.length);
      let view = new DataView(buffer);

      //赋值
      for (let i = 0; i < data.length; i++) {
        view.setUint8(i, data[i]);
      }

      //发送，发送格式为ArrayBuffer
      socket.websocket.send(buffer);
      if (socket.pfnOnTransmitted) {
        socket.pfnOnTransmitted();
      }

      //清零
      socket.fail_number = 0;
    } else {
      socket.fail_number++;
      if (socket.fail_number >= 5) {
        socket.close();
      }
    }
  },

  heartbeat: () => {
    //清除旧定时器
    if (socket.heartbeat_timer) {
      clearInterval(socket.heartbeat_timer);
    }

    //创建新定时器
    socket.heartbeat_timer = setInterval(() => {
      if ((socket.websocket) && (socket.websocket.readyState === socket.websocket.CLOSED)) {
        socket.websocket = null;
        return;
      }

      //定时时间到，发送心跳包数据
      if (socket.heart_buffer.length > 0) {
        socket.send(socket.heart_buffer);
      } else {
        let data = [0x30, 0x31, 0x32, 0x33, 0x34, 0x35];
        socket.send(data);
      }
    }, socket.heartbeat_interval);
  },

  close: () => {
    clearInterval(socket.heartbeat_interval);
    socket.is_reconnect = false;
    if (socket.websocket) {
      console.log('Websocket closes the connection!');
      socket.websocket.close();
    }
  },


  // 重新连接
  reconnect: () => {
    //关闭
    if (socket.websocket) {
      socket.close();
    }

    //调试
    console.log('Reconnect the websocket server!');

    //重连
    socket.connect();
  },

  //读取状态
  getStatus: (): number => {
    if (socket.websocket) {
      return socket.websocket.readyState;
    } else {
      return EnumWebsocketState.WS_NULL;
    }
  }
}
